home *** CD-ROM | disk | FTP | other *** search
/ Archive Magazine CD 1995 / Archive Magazine CD 1995.iso / discs / prog_disc / volume_8 / issue_06 / risc_os / Wimp / Desktop < prev    next >
Encoding:
Text File  |  1988-12-06  |  11.3 KB  |  278 lines

  1. > Wimp.Desktop
  2.  
  3. New Calls
  4. ---------
  5.  
  6.         Wimp_Initialise
  7.         Wimp_CloseDown
  8.         Service_WimpCloseDown
  9.         Wimp_StartTask
  10.  
  11.         *Desktop
  12.         Service_StartWimp
  13.         Service_StartedWimp
  14.         Wimp_Poll: reason code 18 (message) action 0 (global closedown)
  15.  
  16.  
  17. Starting/stopping a task
  18. ------------------------
  19.  
  20. Wimp_Initialise
  21. Entry:  if R1 = "TASK" (low-byte = "T", high-byte = "K"):
  22.            R0 = last known Wimp version number * 100 (at least 200)
  23.            R2 = pointer to short description of task (used by Switcher menu)
  24.            (this is a new-style Wimp task)
  25.         if R1 <> "TASK",
  26.            (this is an old-style Wimp task)
  27. Exit:   R0 = current Wimp version number * 100
  28.         if R1 = "TASK" on entry,
  29.            R1 = task handle on exit
  30.  
  31. Old-style Wimp programs are recognised by the Wimp by the way in which they
  32. call Wimp_Initialise, since they won't set R1 = "TASK" (unless they are
  33. extremely unlucky!).
  34.  
  35. When an old-style wimp application starts up, the Wimp will automatically
  36. open a large window with background colour 15, which covers all other
  37. windows, so that the task has the whole screen to itself.  It will also
  38. prevent any other tasks  from receiving any kind of event from Wimp_Poll
  39. while the old-style task is running.
  40.  
  41. When new tasks start up, the Wimp will set up the mode and pointer (if this
  42. is the first task), whereas it behaves in 'compatible mode' with old tasks,
  43. not doing anything except programming the pointer shape.
  44.  
  45.  
  46. Wimp_CloseDown
  47. Entry:  if R1 = "TASK",
  48.            R0 = task handle of task to be closed down
  49.  
  50. If the task handle is not specified, it is assumed to be whichever task was
  51. last active (ie. the last task that Wimp_Poll returned to).
  52.  
  53. Note that the task handle should always be specified if Wimp_CloseDown is
  54. called in (eg) the 'Die' entry of a module, since the relevant task is
  55. probably not the one currently running.
  56.  
  57. When a live task is killed using Wimp_CloseDown, the following service call is
  58. issued by the Wimp:
  59.  
  60.  
  61. Service_WimpCloseDown (&53)
  62. Entry:  R0 = 0 ==> Wimp_CloseDown was called
  63.         R0 > 0 ==> Wimp_Initialise was called in the same domain
  64.         R2 = task handle of task being closed down
  65.  
  66. Normally a task will close itself down when it has decided to finish, in
  67. which case the service call is somewhat superfluous, but there are two
  68. occasions where the task can be closed down 'automatically', as it were.
  69.  
  70. The first of these happens when OS_Exit is called by the task, and
  71. Wimp_CloseDown has not yet been called.  This can happen if, for example, an
  72. error is generated which is not caught by the task's own error handler - in
  73. this case the Wimp reports the error and calls OS_Exit automatically.  The
  74. service call will come round with R0=0 - in this case, the task receiving
  75. the service call should tidy itself up, and pass on the service (it should
  76. NOT call Wimp_CloseDown !!!).  All registers must be preserved.
  77.  
  78. The second case occurs when Wimp_Initialise is called in the same task domain
  79. as a currently active task.  This can occur, if, for example, the task allows
  80. the user to enter *commands, in which case it is likely that the user will
  81. try to start up another Wimp program.  The Wimp will attempt to close down
  82. the first task before starting up the new one, and will send round the
  83. Service_WimpCloseDown with R0 > 0 (in fact R0=1 initially, but may be
  84. modified by the time the module receives it).  If R0>0, the original task is
  85. allowed to return an error from the service call by pointing R0 at an error
  86. block (a good error message is "Wimp is currently active" (error number
  87. &103)).  The service should not be claimed, so other modules can receive it,
  88. and R0 should be preserved unless an error is to be returned.  If R0 > 1 on
  89. exit from the OS_ServiceCall, the Wimp will return the error to the task
  90. attempting to start up, which will prevent it from doing so.  Note, however,
  91. that application space may well have been overwritten at this stage, so BASIC
  92. programs and the like cannot use this facility!
  93.  
  94. Note that modules should not actually claim this service (set R1=0), since it
  95. is possible that more than one module is interested in a particular task
  96. closing down.
  97.  
  98.  
  99. Wimp_StartTask
  100. Entry:  R0 --> *command to execute
  101.  
  102. This command is used to start up a new Wimp task.  It creates a new 'domain'
  103. for the task, and executes the *command in it.  If and when the task calls
  104. Wimp_Initialise, and then Wimp_Poll, control will be returned to the 'parent'
  105. task (ie. the one which called Wimp_StartTask).
  106.  
  107. Note that Wimp_StartTask cannot be called except from within a new-style Wimp
  108. application.
  109.  
  110.  
  111. Starting the desktop
  112. --------------------
  113.  
  114. Either:  *Desktop
  115. Or:      Wimp is the configured language, entered by the MOS automatically
  116.  
  117. The *desktop command is decoded by the Desktop module, which also supports
  118. the DESKFS filing system, and allows the Desktop module to be entered as a
  119. language.  The *Desktop command cancels the current EXEC file, if any, since
  120. the Desktop will exit immediately if an exec file is in operation (this is so
  121. that SHIFT-BREAK can be used to start up a boot file).
  122.  
  123. When the Desktop is entered (by either of the above methods), it attempts to
  124. 'wake up' any resident modules which would like to become Wimp tasks.  It
  125. does this by passing round a service call Service_StartWimp (&49), which wimp
  126. application modules should respond to as follows:
  127.  
  128.      *  if already running as a Wimp task, do nothing
  129.      *  otherwise claim the service call:
  130.                 set R0 --> *command to start up module
  131.                     R1 = 0 (claim service)
  132.  
  133. The Desktop, on finding that the service call has been claimed, will pass the
  134. value returned in R0 on to Wimp_StartTask, thereby invoking the *command in a
  135. new Wimp domain.
  136.  
  137. The *command should be decoded by the module (by having the command in its
  138. command decoding table - see PRM 'Modules' chapter), and should cause the
  139. module to enter itself as follows:
  140.  
  141.         SWI OS_Module, R0=2, R1-->module title, R2 = R0 on entry to *command
  142.  
  143. (R0 points to the command tail on entry to the *command).
  144.  
  145. Note that it is very important that the module starts itself up as an
  146. application, for the following reasons:
  147.  
  148.      *  Wimp_Poll can only be called from USR mode
  149.      *  the Wimp intercepts the Service_NewApplication call
  150.      *  Arthur's CAO (currently active object) pointer is set up
  151.  
  152. After starting up the module, the Desktop will re-issue the service call, and
  153. will continue in this way until no-one claims the service, at which point it
  154. issues Service_StartedWimp (&4A) to say that it has finished, and exits.  Any
  155. tasks that were started up during the sequence then continue running.
  156.  
  157. Example startup code:
  158.  
  159.         Service
  160.                 LDR     R12,[R12]               ; get workspace pointer
  161.                 TEQ     R1,#Service_StartWimp
  162.                 MOVNE   PC,LR
  163.  
  164.                 Push    "LR"
  165.                 LDR     R14,mytaskhandle
  166.                 TEQ     R14,#0                  ; is module running?
  167.                 MOVEQ   R14,#-1
  168.                 STREQ   R14,mytaskhandle
  169.                 ADREQ   R0,mycommand
  170.                 MOVEQ   R1,#0                   ; if not, claim service
  171.                 Pull    "PC"
  172.  
  173.         mycommand
  174.                 DCB     "foo",0
  175.                 ALIGN
  176.  
  177.         Mycommand_Code                  ; command table points here
  178.                 Push    "LR"
  179.                 MOV     R2,R0           ; R2 --> command tail
  180.                 ADR     R1,ModuleTitle  ; R1 --> module title
  181.                 MOV     R0,#2           ; R0 = ModHandReason_Enter
  182.                 SWI     XOS_Module
  183.                 Pull    "PC"
  184.  
  185. Note that the module must actually enter itself in this way, rather than
  186. simply jumping to its code, since the MOS has to flatten the supervisor stack
  187. and so on, as the new module is a new application.
  188.  
  189.  
  190. Errors
  191. ------
  192.  
  193. A problem arises if any module fails to initialise properly, since after
  194. reporting the error to the user, the module must abort, and the Wimp will
  195. then re-issue the Service_StartWimp call, which will be caught again by the
  196. module, and so on (ie. the user is stuck in an infinite loop).
  197.  
  198. It is better if any errors during initialisation are reported, followed by
  199. the rest of the modules starting up.  To achieve this, the following
  200. procedure must be adopted:
  201.  
  202.      *  When the application module is first loaded, it sets an internal
  203.         variable called 'mytaskhandle' to zero (meaning 'not running')
  204.  
  205.      *  When the module is entered, it should check to see if it is already
  206.         running (mytaskhandle > 0).  If it is, it should first call
  207.         Wimp_CloseDown with R0 = mytaskhandle, R1 = "TASK", to avoid running
  208.         as two tasks at once!  Note: whenever the task closes itself down in
  209.         this way, it should set mytaskhandle=0 afterwards.
  210.  
  211.      *  When the module starts up successfully as a task, it calls
  212.         Wimp_Initialise, and then sets mytaskhandle = R1 (task handle
  213.         returned by Wimp).  The value returned is defined to be greater than
  214.         zero.
  215.  
  216.      *  When the task terminates, the module calls Wimp_CloseDown and sets
  217.         mytaskhandle to 0.
  218.  
  219.      *  When the module is killed, it checks to see if mytaskhandle is
  220.         greater than zero - if it is, it calls Wimp_CloseDown with R0 =
  221.         mytaskhandle and R1 = "TASK" (this tells the Wimp exactly which task
  222.         is to be closed down)
  223.  
  224.      *  When the module receives the Service_StartWimp call, it should
  225.         respond ONLY if mytaskhandle = 0.  If it is, it should set
  226.         mytaskhandle = -1, and return the appropriate *command from the
  227.         service call.
  228.  
  229.      *  If an error occurs during initialisation, the module will not attempt
  230.         to restart, since mytaskhandle = -1.  If the initialisation succeeds,
  231.         mytaskhandle will be overwritten with the appropriate task handle
  232.         value.
  233.  
  234.      *  So that the user can attempt to re-run the module, the Wimp passes
  235.         round another service call when it has finished starting up all
  236.         dormant tasks.  This is Service_StartedWimp (&4A), and when the
  237.         module receives it it should set mytaskhandle to 0, if it was -1
  238.         (without claiming the service).
  239.  
  240.      *  The module should set mytaskhandle=0 when Service_Reset is detected
  241.  
  242.  
  243. Closing down
  244. ------------
  245.  
  246. To make it easier for the user to exit from the Wimp environment, the
  247. switcher module provides a menu entry that allows the user to close down
  248. all tasks.  This causes the switcher to issue a broadcast to all tasks,
  249. asking them to close down, which should be responded to as follows:
  250.  
  251. Wimp_Poll
  252. Exit:  R0 = 18
  253.        R1 --> block (as supplied to Wimp_Poll)
  254.            +0 = 20 (size of block)
  255.            +4 = task handle of Switcher
  256.            +8 = reference number of message
  257.           +12 = 0
  258.           +16 = 0 (global close down)
  259.  
  260. If the task can exit immediately, it should do so (by calling Wimp_CloseDown
  261. followed by OS_Exit or Wimp_Poll).
  262.  
  263. If the task has some unsaved data (eg. the user has modified a file and not
  264. saved it), it should prompt the user (in the same way as it would if the user
  265. had attempted to exit from the task explicitly).  Before it does this,
  266. however, it must abort the close down sequence by acknowledging the close
  267. down message as follows:
  268.  
  269. Wimp_SendMessage
  270. Entry:  R0 = 19 (acknowledge message)
  271.         R1 --> block
  272.             + 12 = reference number of closedown message
  273.  
  274. Once the user has entered a dialogue with any task in this way, therefore, he
  275. must explicitly restart the closedown sequence if he still wishes to quit
  276. from the Wimp environment.
  277.  
  278.